home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PACKET / CBBS60SO.ZIP / MBUTIL.C < prev    next >
Text File  |  1989-02-19  |  16KB  |  807 lines

  1.  
  2. /*
  3.  *  MBUTIL.C - 2/17/88 - Utility functions.
  4.  */
  5.  
  6. #include "mb.h"
  7.  
  8. static char *onoff[2] = { "off", "on" };
  9.  
  10. /*
  11.  *  ! Command: Do DOS command ...
  12.  */
  13.  
  14. dosys()
  15. {
  16.   strcpy(tmp->scr, port->line + 2);
  17.   remnl(tmp->scr);
  18.   if (system(tmp->scr)) perror("Error");
  19. }
  20.  
  21.  
  22. /*
  23.  *  Sort utility.
  24.  *  base is the start of the array of items.
  25.  *  n is the number of items.
  26.  *  w is the item size.
  27.  *  t is scratch space the size of one item.
  28.  */
  29.  
  30. sort(base, n, w, t)
  31. char *base;
  32. int   n;
  33. int   w;
  34. char *t;
  35. {
  36.   register int i;
  37.   register int j;
  38.   register int g;
  39.   char *p1, *p2;
  40.  
  41.   for (g = n/2; g; g /= 2)
  42.   for (i = g; i < n; i++)
  43.   for (j = i - g; j >= 0; j -= g)
  44.   {
  45.     p1 = base + (w * j);
  46.     p2 = base + (w * (j + g));
  47.  
  48.     if (strncmp(p1, p2, w) <= 0) break;
  49.     memcpy(t, p1, w);
  50.     memcpy(p1, p2, w);
  51.     memcpy(p2, t, w);
  52.   }
  53. }
  54.  
  55. /*
  56.  *  Return number of days between two dates.
  57.  */
  58.  
  59. ddiff(fr, to)
  60. char fr[], to[];
  61. {
  62.   register int d;
  63.   static short dpm[13] =
  64.   { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  65.  
  66.   d = 365 * (10 * (to[0] - fr[0]) + to[1] - fr[1]);
  67.  
  68.   d += (dpm[10 * (to[2] - '0') + to[3] - '0'] -
  69.         dpm[10 * (fr[2] - '0') + fr[3] - '0']);
  70.  
  71.   d += 10 * (to[4] - fr[4]) + to[5] - fr[5];
  72.  
  73.   return d;
  74. }
  75.  
  76.  
  77. /*
  78.  *  Wild card match of callsigns with ? and * in first arg.
  79.  */
  80.  
  81. wcm(s1, s2)
  82. char *s1, *s2;
  83. {
  84.   register short l;
  85.  
  86.   if (*s1 is '*') if (matchn(s2, cport->user->call, ln_call)) return false;
  87.  
  88.   for (l = 0; l < ln_call; l++, s1++, s2++)
  89.   {
  90.     if (*s1 is '*') return true;
  91.     if (*s1 isnt '?') if (*s1 isnt *s2) return false;
  92.   }
  93.   return true;
  94. }
  95.  
  96. /*
  97.  *  Save remote sysop command, for later execution.
  98.  */
  99.  
  100. savecmd()
  101. {
  102.   strcpy(scmd, port->line);
  103.   s_param setbit s_cmd;
  104.   port->msg = mdone;
  105. }
  106.  
  107. /*
  108.  *  EP command: change port parameters.
  109.  */
  110.  
  111. edport()
  112. {
  113.   register PORTS *p;
  114.   register int i;
  115.  
  116.   if ((p = findport(*port->fld[1])) is NULL) { port->msg = mnport; return; }
  117.  
  118.   sprintf(tmp->scr, "Change parameters for port %c, %s\n\n", p->id, p->name);
  119.   outstr(tmp->scr);
  120.  
  121.   while (true)
  122.   {
  123.     outstr("Bbs Down Up Gate Illegal Monitor Remote Xparent 1 2 3 Time Cdigi Fwd Error\n");
  124.  
  125.     sprintf(tmp->scr,"%c   %c    %c  %c    %c       %c       %c      %c       %c %c %c %-3d   %d    %-2d  %d\n",
  126.      (p->priv & p_bbs)/p_bbs +'0',
  127.      (p->priv & p_dnload)/p_dnload +'0', (p->priv & p_upload)/p_upload +'0',
  128.      (p->priv & p_gate)/p_gate +'0', (p->priv & p_ilcal)/p_ilcal +'0',
  129.      (p->priv & p_mon)/p_mon +'0', (p->priv & p_sysop)/p_sysop +'0',
  130.      p->tmode +'0',p->ecmon +'0', p->ecuser +'0', p->eccmds +'0',
  131.      p->ctime, p->ndigi, p->fwdmin, p->errmax);
  132.     outstr(tmp->scr);
  133.  
  134.     getcmd();
  135.     if (port->mode & gone) return;
  136.     i = atoi(port->fld[1]);
  137.     switch(port->opt1)
  138.     {
  139.       case 'B' : p->priv flipbit p_bbs;     break;
  140.       case 'C' : p->ndigi = i;              break;
  141.       case 'D' : p->priv flipbit p_dnload;  break;
  142.       case 'E' : p->errmax = i;             break;
  143.       case 'F' : p->fwdmin = i;             break;
  144.       case 'G' : p->priv flipbit p_gate;    break;
  145.       case 'I' : p->priv flipbit p_ilcal;   break;
  146.       case 'M' : p->priv flipbit p_mon;     break;
  147.       case 'R' : p->priv flipbit p_sysop;   break;
  148.       case 'T' : p->ctime = i;              break;
  149.       case 'U' : p->priv flipbit p_upload;  break;
  150.       case 'X' : p->tmode  = 1 - p->tmode;  break;
  151.       case '1' : p->ecmon  = 1 - p->ecmon;  break;
  152.       case '2' : p->ecuser = 1 - p->ecuser; break;
  153.       case '3' : p->eccmds = 1 - p->eccmds; break;
  154.       default  : if (!port->opt1) return;
  155.     }
  156.   }
  157. }
  158.  
  159. /*
  160.  *  ES command: change system parameters.
  161.  */
  162.  
  163. chgparam()
  164. {
  165.   register int i;
  166.  
  167.   while (true)
  168.   {
  169.     outstr("Bell Kill F&B-kill Svc-msg\n");
  170.     sprintf(tmp->scr, "%c    %c    %c        %c\n",
  171.       (s_param & s_page)/s_page+'0', (s_param & s_kill)/s_kill+'0',
  172.       (s_param & s_fkill)/s_fkill+'0', (s_param & s_svc)/s_svc+'0');
  173.     outstr(tmp->scr);
  174.  
  175.     getcmd();
  176.     if (port->mode & gone) return;
  177.     switch(port->opt1)
  178.     {
  179.       case 'B' : s_param flipbit s_page;  break;
  180.       case 'F' : s_param flipbit s_fkill; break;
  181.       case 'K' : s_param flipbit s_kill;  break;
  182.       case 'S' : s_param flipbit s_svc;   break;
  183.       default  : if(!port->opt1) return;
  184.     }
  185.   }
  186. }
  187.  
  188. /*
  189.  *  Screen paging.
  190.  */
  191.  
  192. char *pausemsg;
  193. static char *pghdr = NULL;
  194. static short lnmax;
  195. static short lncnt;
  196.  
  197. /*
  198.  *  If local console, pause until user types a character.
  199.  *  Return the character.
  200.  *  If not local console, just return a blank.
  201.  */
  202.  
  203. char pause()
  204. {
  205.   register char t;
  206.  
  207.   if (port->mode is local)
  208.   if (!pt_flag)
  209.   {
  210.     prtx(pausemsg);
  211.     t = inchar();
  212.     outchar('\n');
  213.     return toupper(t);
  214.   }
  215.   return ' ';
  216. }
  217.  
  218. /*
  219.  *  Start screen paging.
  220.  */
  221.  
  222. pgst(cp)
  223. char *cp;
  224. {
  225.   if ((pghdr = cp) is NULL) lnmax = 23; else lnmax = 22;
  226.   lncnt = lnmax;
  227. }
  228.  
  229. /*
  230.  *  Pause if full screen.
  231.  */
  232.  
  233. char pgck()
  234. {
  235.   if (--lncnt) return ' ';
  236.   lncnt = lnmax;
  237.   return pause();
  238. }
  239.  
  240. /*
  241.  *  Display header if at top of screen.
  242.  */
  243.  
  244. pghd()
  245. {
  246.   if (lncnt is lnmax) if (pghdr isnt NULL) outstr(pghdr);
  247. }
  248.  
  249. /*
  250.  *  Pause if required at last line.
  251.  */
  252.  
  253. pgdn()
  254. {
  255.   if (lncnt isnt lnmax) pause();
  256. }
  257.  
  258. /*
  259.  *  Display "no such file" message, and file name.
  260.  */
  261.  
  262. nofile(c)
  263. char *c;
  264. {
  265.   prtx(mnfile); outstr(c); outchar('\n');
  266. }
  267.  
  268. /*
  269.  *  Memory allocation problem, just plain quit.
  270.  */
  271.  
  272. errall()
  273. {
  274.   outstr("Not enough memory\n");
  275.   exit (0);
  276. }
  277.  
  278. /*
  279.  *  Is this a callsign?
  280.  */
  281.  
  282. iscall(c)
  283. char *c;
  284. {
  285.   register short i, ld, nd;
  286.  
  287.   nd = 0;
  288.   for (i = 0; (i < ln_call) and (*c isnt ' '); i++, c++)
  289.   {
  290.     if (ld = isdigit(*c)) nd++;
  291.   }
  292.   return ((i > 3) and ((nd is 1) or (nd is 2)) and !ld);
  293. }
  294.  
  295. /*
  296.  *  Print list of ports and port names.
  297.  */
  298.  
  299. shports()
  300. {
  301.   register PORTS *p;
  302.  
  303.   sprintf(port->line, "Use %c and port ID:\n", port->opt1);
  304.   outstr(port->line);
  305.   for (p = porthd; p isnt NULL; p = p->next)
  306.   {
  307.     sprintf(port->line, "%c%c  %s\n", port->opt1, p->id, p->name);
  308.     outstr(port->line);
  309.   }
  310. }
  311.  
  312. /*
  313.  *  Return pointer to port with id pid, or NULL.
  314.  */
  315.  
  316. PORTS *findport(pid)
  317. char pid;
  318. {
  319.   register PORTS *p;
  320.  
  321.   for (p = porthd; p isnt NULL; p = p->next) if (p->id is pid) return p;
  322.   return NULL;
  323. }
  324.  
  325. /*
  326.  *  Is it?
  327.  */
  328.  
  329. iseof(cp)
  330. char *cp;
  331. {
  332.   return match(cp, "*** EOF\n");
  333. }
  334.  
  335. /*
  336.  *  Remove new line  and control characters from end of string.
  337.  */
  338.  
  339. remnl(p)
  340. char *p;
  341. {
  342.   for (; *p; p++)
  343.   {
  344.     if (*p is '\n') { *p = '\0'; return; }
  345.     if (*p < ' ') *p = ' ';
  346.   }
  347. }
  348.  
  349. /*
  350.  *  Parse a callsign.
  351.  *  Blank pad the output field, remove trailing ssid from call.
  352.  *  Return the SSID.
  353. */
  354.  
  355. pcall(c, p)
  356. char *c;
  357. char *p;
  358. {
  359.   register short i;
  360.  
  361. /*
  362.  *  Blank fill the target buffer.
  363.  */
  364.  
  365.   fill (c, ' ', ln_call);
  366.  
  367. /*
  368.  *  Ignore leading spaces.
  369.  */
  370.  
  371.   while (*p and (*p is ' ')) p++;
  372.  
  373. /*
  374.  *  Copy the call from the string into the call buffer.
  375.  */
  376.  
  377.   for (i = ln_call; i and *p; i--)
  378.   {
  379.     if (*p <= ' ') return 0;
  380.     if (*p is '-') return atoi(++p);
  381.     if (*p is '.') return 0;
  382.     *c++ = *p++;
  383.   }
  384.   if (*p++ is '-') return atoi(p); else return 0;
  385. }
  386.  
  387. /*
  388.  *  Is the string a number?
  389.  */
  390.  
  391. num(p)
  392. char *p;
  393. {
  394.   for (; *p; p++) if (!isdigit(*p)) return false;
  395.   return true;
  396. }
  397.  
  398. /*
  399.  *  "Output, no blanks".
  400.  */
  401.  
  402. outnb(p, n)
  403. char *p;
  404. short n;
  405. {
  406.   while (n--) switch (*p)
  407.   {
  408.     case ' ' :
  409.     case '\n' :
  410.     case '\0' : return;
  411.     default: outchar(*p++);
  412.   }
  413. }
  414.  
  415. /*
  416.  *  Print a number right justified in a fixed width field.
  417.  */
  418.  
  419. outnr(i, n)
  420. int   i;  /* The number to print */
  421. short n;  /* Field width */
  422. {
  423.   char num[7];
  424.  
  425.   sprintf (num, "%-6u", i);
  426.   outnb (num, n);
  427. }
  428.  
  429. /*
  430.  *  Display software version.
  431.  */
  432.  
  433. prtver()
  434. {
  435.   outstr(ver); outchar('\n');
  436. }
  437.  
  438. /*
  439.  *  Print multi-line message.
  440.  */
  441.  
  442. prtm(m)
  443. MLM *m;
  444. {
  445.   register MLM *p;
  446.  
  447.   for (p = m; p isnt NULL; p = p->next) prtx(p->text);
  448. }
  449.  
  450. /*
  451.  *  Print a string, expanding the "$" fields.
  452.  */
  453.  
  454. prtx(p)
  455. char *p;
  456. {
  457.  
  458.   for (; *p; p++)
  459.   {
  460.     if (*p isnt '$') outchar(*p);
  461.     else switch (*(++p))
  462.     {
  463.       case 'A' : outnb(port->mmhs->bbs, ln_call); break;
  464.       case 'B' : outchar(port->mmhs->type); break;
  465.       case 'C' : outnr(mfhs->next_msg, 5); break;
  466.       case 'D' : outstr(l_date); break;
  467.       case 'E' : outstr(port->mmhs->title); break;
  468.       case 'F' : outstr(port->lport->name); break;
  469.       case 'G' : outnb(port->mmhs->to, ln_call); break;
  470.       case 'H' : p++; break;
  471.       case 'I' : outnb(port->user->handle, ln_handle); break;
  472.       case 'J' : outnb(port->mmhs->date, ln_date); break;
  473.       case 'K' : outnb(port->mmhs->time, ln_time); break;
  474.       case 'L' : outnr(mfhs->next_msg - 1, 5); break;
  475.       case 'M' : outnr(port->mmhs->number, 5); break;
  476.       case 'N' : outnr(mfhs->count, 4); break;
  477.       case 'O' : outnb(cport->user->call, ln_call); break;
  478.       case 'P' : outnb(port->mmhs->from, ln_call); break;
  479.       case 'Q' : outstr(qth); break;
  480.       case 'R' : outnb(port->rcall, ln_call); break;
  481.       case 'S' : outnb(port->lport->user->call, ln_call); break;
  482.       case 'T' : outnb(l_time, ln_time); break;
  483.       case 'U' : outnb(port->user->call, ln_call); break;
  484.       case 'V' : outstr(ver); break;
  485.       case 'W' : outnb(port->lport->user->handle, ln_handle); break;
  486.       case 'X' : outnb(port->user->date, ln_date); break;
  487.       case 'Y' : outnb(port->user->time, ln_time); break;
  488.       case 'Z' : outnr(port->user->msg_number, 5); break;
  489.       case 'a' : outstr(orgbbs); break;
  490.       case 'h' : outstr(port->mmhs->call); break;
  491.       case 'j' : outstr(orgdate); break;
  492.       case 'k' : outstr(orgtime); break;
  493.       case 'm' : outstr(orgmsg); break;
  494.       default  : outchar(*p);
  495.     }
  496.   }
  497. }
  498.  
  499. /*
  500.  *  Write random record.
  501.  */
  502.  
  503. write_rec(fid, rec, buffer)
  504. int fid;
  505. int rec;
  506. char buffer[];
  507. {
  508.   long lseek();
  509.   long offs;
  510.  
  511.   offs = (long)rec * (long)RECSIZE;
  512.   lseek(fid, offs, 0);
  513.   return (write(fid, buffer, RECSIZE) is RECSIZE);
  514. }
  515.  
  516. /*
  517.  *  Read random record.
  518.  */
  519.  
  520. read_rec(fid, rec, buffer)
  521. int fid;
  522. int rec;
  523. char buffer[];
  524. {
  525.   long lseek();
  526.   long offs;
  527.  
  528.   offs = (long)rec * (long)RECSIZE;
  529.   lseek(fid, offs, 0);
  530.   return (read(fid, buffer, RECSIZE) is RECSIZE);
  531. }
  532.  
  533. /*
  534.  *  Fill buffer with characters from the current input,
  535.  *  until CR or buffer overflow. Terminate buffer with
  536.  *  '\0', thus making it a string.
  537.  *  Translate \r to \n.
  538.  *  Ignore \n.
  539.  *  Deal with backspace and things like that.
  540.  *  Set flags for timeout and disconnect.
  541.  */
  542.  
  543. getdat()
  544. {
  545.   register char *cp;
  546.   register PORTS *p;
  547.   register char ch;
  548.  
  549.   p = port;
  550.  
  551.   if (p->flags & p_dotmr)
  552.   {
  553.     if ((p->mode & idle) and (p->dev is p_tnc)) settmr(&p->itime, 2);
  554.     else settmr(&p->itime, p->ctime);
  555.   }
  556.  
  557.   p->flags setbit p_dotmr;
  558.   cp = p->line;
  559.  
  560.   while (true)
  561.   {
  562.     while(!instat())
  563.     {
  564.       if (p isnt cport)
  565.       {
  566.         ioport(cport);
  567.         if (instat())
  568.         {
  569.           ch = inchar();
  570.  
  571.           if (ch is achar)
  572.           {
  573.             p->mode = forced;
  574.             ioport(p);
  575.             return true;
  576.           }
  577.  
  578.           if (ch is tchar)
  579.           {
  580.             p->flags setbit p_opreq;
  581.             ioport(p);
  582.             return true;
  583.           }
  584.  
  585.         }
  586.         ioport(p);
  587.       }
  588.       if (p->flags & p_trans)
  589.       if (!isdcd())
  590.           {
  591.           if (!(p->mode & idle)) p->mode = discon;
  592.           return true;
  593.           }
  594.  
  595.       if (!chktmr(p->itime))
  596.       {
  597.         *cp = '\0';
  598.         if (!(p->mode & idle)) p->mode = timeout;
  599.         return true;
  600.       }
  601.     }
  602.  
  603.     *cp = inchar();
  604.  
  605. /*
  606.  *  Got a character, deal with it.
  607.  */
  608.  
  609.     if ((cp is (p->line + linelen - 2)) or (*cp is '\r'))
  610.     {
  611. /*
  612.  *  Got a whole line. Either buffer full, or character is CR.
  613.  */
  614.       if (*cp is '\r') *cp = '\n';
  615.       cp++; *cp = '\0';
  616.  
  617.       if (p->flags & p_echo) outchar('\n');
  618.       if (!(p->flags & p_trans))
  619.       {
  620.          if (isdis(p->line))
  621.          {
  622.            if (!(p->mode & idle)) p->mode = discon;
  623.            return true;
  624.          }
  625.          if (isretry(p->line)) return false;
  626.  
  627.          if (isreq(p->line))
  628.          {
  629.            p->flags setbit p_req;
  630.            pcall(p->rcall, p->line + 20);
  631.            p->flags clrbit p_dotmr;
  632.            return false;
  633.          }
  634.       }
  635.       return true;
  636.     }
  637.  
  638. /*
  639.  *  Not end of line.
  640.  *  Stuff the character in the buffer.
  641.  *  Handle some control characters. Ignore some.
  642.  */
  643.  
  644.     switch(*cp)
  645.     {
  646.       default   : if (p->flags & p_echo) outchar(*cp); cp++; break;
  647.       case '\b' :
  648.         if (cp > p->line) { cp--; if (p->flags & p_echo) outstr("\b \b"); }
  649.         break;
  650.  
  651.       case '\n' : if (cp is p->line) { *cp = '\0'; return false; }
  652.       case '\0' : ;   /* Ignore most ctl char */
  653.       case ctl_c: ;   /* Ignore most ctl char */
  654.       case ctl_v: ;   /* Ignore most ctl char */
  655.     }
  656.   }
  657. }
  658.  
  659. /*
  660.  *  Is the string a header line?
  661.  */
  662.  
  663. ishead(p)
  664. char *p;
  665. {
  666.   if (!*p or (*p is '\n')) return false;      /* end of headers */
  667.   if (strnicmp(p, "R:" ,2) and strnicmp(p, "I:", 2)) return false;
  668.   return true;
  669. }
  670.  
  671. /*
  672.  *  Parse a command line.
  673.  *
  674.  *  Input:   Line of text in port->line.
  675.  *  Returns: Fields are placed in port->cmd.
  676.  *           Fields are pointed to by port->fld[].
  677.  *           port->flds is set to the number of fields found.
  678.  *           Each field is null-terminated.
  679.  *           Fields beyond maxflds are ignored.
  680.  */
  681.  
  682. parse()
  683. {
  684.   register short bl;
  685.   register char *in, *out;
  686.  
  687.   for (port->flds = 0; port->flds < maxflds;)
  688.     port->fld[port->flds++] = nullstr;
  689.  
  690.   in  = port->line;
  691.   out = port->cmd;
  692.   bl  = false;
  693.   port->flds = 0;
  694.  
  695.   while (*in and (port->flds < maxflds) and (out < (port->cmd + cmdlen - 1)))
  696.   {
  697.     *out = toupper(*in);
  698.     if (bl)
  699.     {
  700.       if ((*in <= ' ') or ((*in is '@') and (port->flds is 2)))
  701.       {
  702.         bl = false;
  703.         *out = '\0';
  704.         if (*in is '@')
  705.         {
  706.           out++;
  707.           *out = '@';
  708.           port->fld[port->flds++] = out++;
  709.           *out = '\0';
  710.         }
  711.       }
  712.       out++;
  713.     }
  714.     else
  715.     {
  716.       if (*in > ' ')
  717.       {
  718.         bl = true;
  719.         port->fld[port->flds++] = out++;
  720.       }
  721.     }
  722.     in++;
  723.   }
  724.   *out = '\0';
  725.  
  726.   port->opt1 = *port->fld[0];
  727.   port->opt2 = *(port->fld[0] + 1);
  728.   if (!port->opt2) port->opt2 = ' ';
  729. }
  730.  
  731. /*
  732.  *  Bundle getdat and parse.
  733.  */
  734.  
  735. getcmd()
  736. {
  737.   while(!getdat());
  738.   parse();
  739. }
  740.  
  741. /*
  742.  *  Fill some memory with a character.
  743.  */
  744.  
  745. fill(adr, ch, len)
  746. char *adr;
  747. char ch;
  748. int len;
  749. {
  750.   while (len--) *adr++ = ch;
  751. }
  752.  
  753. /*
  754.  *  Copy C string to LJSF string.
  755.  */
  756.  
  757. ljsf(to, from, size)
  758. char *to;
  759. char *from;
  760. int  size;
  761. {
  762.   fill(to, ' ', size);
  763.   while (size--)
  764.   {
  765.     if (*from < ' ') return;
  766.     *to++ = *from++;
  767.   }
  768. }
  769.  
  770. /*
  771.  *  Copy LJSF string to C string.
  772.  */
  773.  
  774. unbl(to, from, size)
  775. char *to, *from;
  776. int size;
  777. {
  778.   while (size--)
  779.   {
  780.     if (*from <= ' ') { *to = '\0'; return; }
  781.     *to++ = *from++;
  782.   }
  783.   *to = '\0';
  784. }
  785.  
  786. /*
  787.  *  Are you sure? .....
  788.  */
  789. sure()
  790. {
  791.   outstr("Are you sure (Y/N)?\n");
  792.   while (!getdat());
  793.   if (toupper(*port->line) is 'Y') return false;
  794.   return true;
  795. }
  796.  
  797. /* Search string for match */
  798.  
  799. search(a,b,c)
  800. char *a, *b;
  801. int c;
  802. {
  803.   for( ; *a; a++)
  804.     if (matchn(a, b, c)) return true;
  805.   return false;
  806. }
  807.